# -*- coding: utf-8 -*-
"""
@Time ： 2021/11/23 20:21
@Auth ： Mr. William 1052949192
@Company ：特斯汀学院 @testingedu.com.cn
@Function ：Web自动化关键字库
"""
import re
import time
from time import sleep

import pytest
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select

from common.decs import relations
from common.verify import Verify


class Web:
    """面向对象封装常用功能关键字"""

    def __init__(self):
        """构造函数，初始化示例变量"""
        # python3.7以上版本，在初始化的时候，可以给一个默认类型
        # 方便后续使用时，可以点出方法
        self.driver: webdriver.Chrome = None
        # 关联的字典
        self.relations = {}
        # 图文验证码识别
        self.verify = Verify('wuqingfqng', '6e8ebd2e301f3d5331e1e230ff3f3ca5', '904357')

    def myslide(self,locator1='',locator2=''):
        """
        12306滑块关键字
        :param locator1: 滑块的定位器
        :param locator2: 滑动距离的定位器
        """
        ele1 = self.__find_ele(locator1)
        ele2 = self.__find_ele(locator2)
        # 使用action滑动
        action = ActionChains(self.driver)
        # 按住滑块
        action.click_and_hold(ele1)
        # 拖到最右边
        action.move_by_offset(ele2.size.get('width'), 0)
        # 松开鼠标
        action.release()
        # 让这些动作执行
        action.perform()

    def getverify(self,locator = ""):
        """
        给验证码图片截图，并且识别为文字
        :param locator: 支持xpath和id
        :return: 验证码
        """
        ele = self.__find_ele(locator)
        # 截图
        ele.screenshot('./lib/verify.png')
        # 识别验证码
        ver = self.verify.PostPic(1902, im='./lib/verify.png')
        # 保存验证码
        self.relations['verify'] = ver
        return ver

    def gettitle(self):
        time.sleep(1)
        self.relations['title'] = self.driver.title
        print(self.relations.get('title'))
        return self.relations.get('title')

    @relations
    def openbrowser(self, br=''):
        """
        打开浏览器
        :param br: gc=Chrome，ie=Ie，默认是Chrome
        """
        if br == '' or br == 'gc':
            # 使用options，去掉自动化软件控制的标识
            option = Options()
            option.add_experimental_option('excludeSwitches', ['enable-automation'])
            option.add_argument('--disable-blink-features=AutomationControlled')
            prefs = {}
            prefs['credentials_enable_service'] = False
            prefs['profile.password_manager_enabled'] = False
            option.add_experimental_option('prefs', prefs)  ##关掉密码弹窗

            option.add_argument('–disable-gpu')  # 谷歌文档提到需要加上这个属性来规避bug
            option.add_argument('lang=zh_CN.UTF-8')  # 设置默认编码为utf-8
            self.driver = webdriver.Chrome(options=option)
        elif br == 'ie':
            self.driver = webdriver.Ie()
        else:
            self.driver = webdriver.Chrome()

        # 隐式等待：如果立即没找到元素，就等一秒再找，直到找到或者报错（整个浏览器生效）
        self.driver.implicitly_wait(10)
        # 最大化
        self.driver.maximize_window()

    @relations
    def geturl(self, url=''):
        """
        访问网站
        :param url: http/https开头的标准url
        :return:
        """
        self.driver.get(url)

    def __find_ele(self, locator=''):
        """
        私有函数，定位元素
        :param locator: 支持xpath和id
        :return: 返回找到元素，或者为空
        """
        # 以/开头的都是xpath
        if locator.startswith('/') or locator.startswith('(/'):
            ele = self.driver.find_element(By.XPATH, locator)
        else:
            # 其他的，认为是id
            ele = self.driver.find_element(By.ID, locator)

        if ele:
            self.driver.execute_script('arguments[0].style="background: rgb(251 40 234);"', ele)

        # # 在这里加一个元素是否能被操作，不能就继续等
        # while ele:
        #     try:
        #         print(ele.text)
        #         break
        #     except Exception as e:
        #         time.sleep(1)

        return ele

    @relations
    def input(self, locator='', value=''):
        """
        找到元素并输入value
        :param locator: 定位表达式，支持xpath和id
        :param value: 需要输入的值
        """
        ele = self.__find_ele(locator)
        if value.endswith('.png'):
            value = 'D:/PythonPro/VIPPRO/VipFrame10/lib/' + value
            ele.send_keys(value)
        else:
            value = value + ' '
            ele.send_keys(value)
            ele.send_keys(Keys.BACKSPACE)

    def clear(self, locator=''):
        """
        清空输入框
        :param locator: 定位表达式，支持xpath和id
        """
        ele = self.__find_ele(locator)
        ele.click()
        ele.clear()

    @relations
    def click(self, locator=''):
        """
        找到并点击元素
        :param locator: 定位表达式，支持xpath和id
        """
        ele = self.__find_ele(locator)
        ele.click()

    @relations
    def jsclick(self, locator):
        """
        通过js完成找到元素和点击
        :param locator:定位表达式，支持xpath和id
        """
        ele = self.__find_ele(locator)
        self.driver.execute_script('arguments[0].click()', ele)

    @relations
    def gettext(self, locator='', reg=''):
        """
        找到元素，并获取元素的文本值
        :param locator: 定位表达式，支持xpath和id
        :param reg: 提取文本的正则表达式
        """
        ele = self.__find_ele(locator)
        text = ele.text
        # 如果传了正则，就使用正则处理
        if reg:
            text = re.findall(r'\d{18}', text)
            if text:
                text = text[0]
            else:
                text = ''

        # 我们把获得的文本，用text键存到字典里面
        self.relations['text'] = text
        print(text)
        return text

    @relations
    def assertcontains(self,expect='',actual=''):
        """
        断言，实际结果里面包含期望值
        :param expect: 期望值
        :param actual: 实际结果
        """
        if str(actual).__contains__(str(expect)):
            print('PASS')
        else:
            pytest.fail('断言失败')

    def sleep(self, t=''):
        """
        固定等待
        :param t: 等待的时间，单位s
        """
        t = float(t)
        sleep(t)

    @relations
    def intoiframe(self, locator=''):
        """
        找到并进入iframe
        :param locator: 定位表达式，支持xpath和id
        """
        ele = self.__find_ele(locator)
        self.driver.switch_to.frame(ele)

    def outiframe(self):
        """
        退出到最外面
        """
        self.driver.switch_to.default_content()

    @relations
    def select(self, locator='', text=''):
        """
        通过文本选择下拉框
        :param locator:
        :param text:
        :return:
        """
        ele = self.__find_ele(locator)
        select = Select(ele)
        select.select_by_visible_text(text)

    @relations
    def moveto(self, locator=''):
        """
        鼠标移动到元素
        :param locator:
        :return:
        """
        ele = self.__find_ele(locator)
        actions = ActionChains(self.driver)
        actions.move_to_element(ele)
        # 使actions的所有操作生效
        actions.perform()

    @relations
    def switchwin(self, win):
        """
        可以通过下标或者title切换
        :param win: 传整数，就是通过下标切换，
                    传字符串，就是通过title切换
        """
        handles = self.driver.window_handles
        if type(win) == int:
            self.driver.switch_to.window(handles[win])
        else:
            # 从第一个窗口开始切换
            for i in range(len(handles)):
                self.driver.switch_to.window(handles[i])
                # 如果切换到窗口，它的标题包含传的标题，就算找到了
                if self.driver.title.__contains__(win):
                    break

    def quit(self):
        """
        退出浏览器
        """
        self.driver.quit()
